package com.xinruke.hostels.reservation.service;

import com.alibaba.fastjson.JSONObject;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.xinruke.hostels.cache.extract.extractor.DictInfoCacheExtractor;
import com.xinruke.hostels.cache.extract.extractor.HotelInfoCacheExtractor;
import com.xinruke.hostels.cache.extract.extractor.ReservationCacheExtractor;
import com.xinruke.hostels.central.manage.interfaces.dto.HotelInfoDetailQueryDTO;
import com.xinruke.hostels.central.manage.interfaces.dto.HotelInfoDetailQueryResultDTO;
import com.xinruke.hostels.common.cache.ReservationUserCache;
import com.xinruke.hostels.common.cache.vo.LoginReservationResultVO;
import com.xinruke.hostels.common.constants.RedisConstants;
import com.xinruke.hostels.common.constants.SysDicConstant;
import com.xinruke.hostels.common.exception.ArgumentException;
import com.xinruke.hostels.common.exception.BizException;
import com.xinruke.hostels.common.mybatis.MyExample;
import com.xinruke.hostels.common.po.*;
import com.xinruke.hostels.common.po.constants.YwFangtairiqijiluConstants;
import com.xinruke.hostels.common.po.constants.YwYudingDingdanConstants;
import com.xinruke.hostels.common.po.constants.YwYudingDingdanZixiangConstants;
import com.xinruke.hostels.common.service.OperateLogService;
import com.xinruke.hostels.common.util.CustomSecurity;
import com.xinruke.hostels.common.util.DateCalendarUtil;
import com.xinruke.hostels.common.vo.ResultVO;
import com.xinruke.hostels.common.vo.query.EConditionOperator;
import com.xinruke.hostels.common.vo.query.QueryConditions;
import com.xinruke.hostels.common.vo.query.RowsDataVO;
import com.xinruke.hostels.dailymanage.interfaces.api.DailyManageApi;
import com.xinruke.hostels.dailymanage.interfaces.dto.RemainCountQueryDto;
import com.xinruke.hostels.dailymanage.interfaces.dto.RoomReservationQueryDTO;
import com.xinruke.hostels.dailymanage.interfaces.dto.RoomReservationResultDTO;
import com.xinruke.hostels.reservation.interfaces.dto.*;
import com.xinruke.hostels.reservation.interfaces.vo.YudingDingdanZixiangVO;
import com.xinruke.hostels.reservation.mapper.YwFangjianleixingMapper;
import com.xinruke.hostels.reservation.mapper.YwFangtairiqijiluMapper;
import com.xinruke.hostels.reservation.mapper.YwYudingDingdanMapper;
import com.xinruke.hostels.reservation.mapper.YwYudingDingdanZixiangMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import tk.mybatis.mapper.entity.Example;
import tk.mybatis.mapper.util.Sqls;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @author GuoZheng
 * @ClassName RoomService
 * @date：2019/6/12
 * @version: V1.0.0
 * @description：
 */
@Service
@Slf4j
public class RoomOrderService {
    @Autowired
    private YwFangjianleixingMapper fangjianleixingMapper;

    @Resource
    private DailyManageApi dailyManageApi;

    @Resource
    private ReservationUserCache userCache;
    @Value("${hotel.discounts.jiage}")
    private BigDecimal youhuijine;

    @Resource
    private ReservationHotelService hotelService;

    @Resource
    private YwYudingDingdanMapper ywYudingDingdanMapper;

    @Resource
    private YwYudingDingdanZixiangMapper ywYudingDingdanZiXiangMapper;

    @Autowired
    YwFangtairiqijiluMapper fangtairiqijiluMapper;

    @Autowired
    OperateLogService operateLogService;

    @Resource
    private ReservationCacheExtractor reservationCacheExtractor;
    @Resource
    private HotelInfoCacheExtractor hotelInfoCacheExtractor;
    @Resource
    private DictInfoCacheExtractor dictInfoCacheExtractor;

    @Resource
    private DiscountsService discountsService;

    @Resource(name = "commonRedisTemplate")
    RedisTemplate commonRedisTemplate;


    /**
     * 展示当前用户的房间订单列表
     *
     * @param params
     * @return
     */
    public ResultVO<RowsDataVO<RoomOrderListQueryResultDTO>> list(RoomOrderListQueryDTO params) {

        ResultVO resultVO = ResultVO.fail();
        RowsDataVO<RoomOrderListQueryResultDTO> dataVO = new RowsDataVO();

        String order = params.getOrderFields().stream().filter(o -> !StringUtils.isEmpty(o.getOrderField())).map(o -> o.getOrderField() + (o.getOrderDesc() ? " DESC" : " ASC")).reduce((s1, s2) -> s1 + "," + s2).orElse("");
        Page<RoomOrderListQueryResultDTO> page = PageHelper.startPage(params.getPageNo(), params.getPageSize(), order);
        //当前用户信息
        params.setCurrentUserId(userCache.getCurrentUserId());
        //查询
        List<RoomOrderListQueryResultDTO> rows = ywYudingDingdanMapper.selectOrderList(params);

        rows.forEach(r -> {
            //调用接口 填充酒店名称
            HotelInfoDetailQueryResultDTO hotelInfo = hotelInfoCacheExtractor.getJiudianInfoById(r.getJiudianId());
            if (hotelInfo != null) {
                r.setJiudianMingcheng(hotelInfo.getMingcheng() + "(" + hotelInfo.getXiangxidizhi() + ")");
            }
            //字典
            r.setZhuangtaiMinCheng(dictInfoCacheExtractor.getDictValue(SysDicConstant.DINGDANZHUANGTAI, r.getZhuangtai()));
            if (r.getRuzhutianshu() != null){
                r.setYouhuijia(r.getYouhuijia().multiply(BigDecimal.valueOf(r.getRuzhutianshu())));
            }
        });
        dataVO.setPageNo(page.getPageNum());
        dataVO.setTotalRecords(page.getTotal());
        dataVO.setTotalPages(page.getPages());
        dataVO.setRows(rows);

        resultVO.setCode(ResultVO.SUCCESS);
        resultVO.setMessage("sucess");
        resultVO.setData(dataVO);


        return resultVO;
    }

    @Transactional
    public ResultVO submit(RoomOrderSubmitInfoDTO params) {
        //校验是否可预订
        checkIsCanReservation(params);

        String dingdanhao = String.valueOf(new Date().getTime()).substring(5);

        YwYudingDingdan mhDingdan = new YwYudingDingdan();
        BeanUtils.copyProperties(params, mhDingdan);
        //基础字段赋值
        mhDingdan.setDingdanhao(dingdanhao);
        mhDingdan.setShanchubiaoshi(YwYudingDingdanConstants.SHANCHUBIAOSHI_BUSHANCHU);
        mhDingdan.setZhuangtai(YwYudingDingdanConstants.ZHUANGTAI_YITIJIAO);
        mhDingdan.setPingjiazhuangtai(YwYudingDingdanConstants.PINGJIAZHUANGTAI_WEIPINGJIA);
        mhDingdan.setChuangjianshijian(new Date());
        mhDingdan.setGengxinshijian(new Date());
        mhDingdan.setYudingriqi(new Date());
        mhDingdan.setRuzhuleixing(YwYudingDingdanConstants.RUZHULEIXNG_QUANTIAN);
        mhDingdan.setKeyuanleixing(YwYudingDingdanConstants.KEYUANLEIXING_SANKE);
        mhDingdan.setYudingleixing(YwYudingDingdanConstants.YUDINGLEIXING_GEREN);
        mhDingdan.setLaiyuan(YwYudingDingdanConstants.LAIYUAN_WANGZHAN);
        //计算预订房间数
        Integer roomCount = params.getRoomReservationInfoDto().stream().map(RoomOrderInfoQueryDto::getShuliang).reduce(Integer::sum).orElse(0);
        mhDingdan.setYudingfangjianshu(roomCount);

        //填充用户信息字段
        LoginReservationResultVO userInfo = userCache.getLoginReservationUserInfo();
        mhDingdan.setYudingrenxingming(userInfo.getXingming());
        mhDingdan.setYudingrendianhua(userInfo.getShoujihao());
        //当前用户id
        mhDingdan.setHuiyuanId(userInfo.getId());
        mhDingdan.setZhengjianleixing(MhHuiyuanQinshu.ZHENGJIANLEIXING_SHENFENZHENG);
        mhDingdan.setZhengjianhao(userInfo.getShenfenzhenghao());
        int i = ywYudingDingdanMapper.insertSelective(mhDingdan);
        if (i < 1) {
            throw new ArgumentException("预订失败");
        }


        //填充房间信息列表-锁房
        List<YwYudingDingdanZixiang> list = params.getRoomReservationInfoDto().stream().map(r -> {

            YwYudingDingdanZixiang dingdanZixiang = new YwYudingDingdanZixiang();
            BeanUtils.copyProperties(r, dingdanZixiang);
            dingdanZixiang.setDingdanhao(dingdanhao);
            dingdanZixiang.setChuangjianshijian(new Date());
            dingdanZixiang.setDingdanId(mhDingdan.getId());
            //dingdanZixiang.setYudingrenshenfenId(r.getYudingrenId());
            dingdanZixiang.setShanchubiaoshi(YwYudingDingdanZixiangConstants.SHANCHUBIAOSHI_BUSHANCHU);
            /*ContactsDetailQueryDTO contactsDetailQueryDTO = new ContactsDetailQueryDTO();
            contactsDetailQueryDTO.setId(r.getYudingrenId());
            ContactsDetailResultDto contactsDetail = reservationUserApi.contactDetailNoCode(contactsDetailQueryDTO).getData();*/
            MhHuiyuanQinshu huiyuanQinshu = reservationCacheExtractor.getMhHuiyuanQinshu(r.getYudingrenId());
            dingdanZixiang.setYudingrenzhengjianhao(huiyuanQinshu.getShenfenzhenghao());
            dingdanZixiang.setYudingrenzhengjianleixing(huiyuanQinshu.getZhengjianleixing());
            dingdanZixiang.setRuzhutianshu(DateCalendarUtil.getDiffDays(r.getRuzhushijian(), r.getLikaishijian()));

            RoomReservationQueryDTO queryDTO = new RoomReservationQueryDTO();
            queryDTO.setJiudianId(r.getJiudianId());
            queryDTO.setEndTime(r.getLikaishijian());
            queryDTO.setFangxingId(r.getFangxingId());
            queryDTO.setOrderId(mhDingdan.getId());
            queryDTO.setStartTime(r.getRuzhushijian());
            ResultVO<RoomReservationResultDTO> reservationResultDTOResultVO = dailyManageApi.roomReservation(queryDTO);
            if (reservationResultDTOResultVO.getCode() != ResultVO.SUCCESS) {
                throw new ArgumentException("锁房失败");
            }
            //填充锁房信息
            RoomReservationResultDTO resultDTO = reservationResultDTOResultVO.getData();
            dingdanZixiang.setFangjianId(resultDTO.getRoomId());
            dingdanZixiang.setFangjianhao(resultDTO.getFangjianbianhao());
            //log.info("得到的门市总价为：{},得到的优惠过后的价格为：{},两者比较过后：{}",r.getMendianjia().multiply(new BigDecimal(DateCalendarUtil.getDiffDays(r.getRuzhushijian(),r.getLikaishijian()))).toString(),r.getYouhuijia().toString(),r.getMendianjia().multiply(new BigDecimal(DateCalendarUtil.getDiffDays(r.getRuzhushijian(),r.getLikaishijian()))).compareTo(r.getYouhuijia()));
            //dingdanZixiang.setShifouyouhui(r.getMendianjia().multiply(new BigDecimal(DateCalendarUtil.getDiffDays(r.getRuzhushijian(),r.getLikaishijian()))).compareTo(r.getYouhuijia())!=0);

            if (r.getRuzhuxingzhi() == YwYudingDingdanZixiangConstants.RUZHUXINGZHI_YINSI && r.getMendianjia().compareTo(r.getYouhuijia()) != 0) {
                dingdanZixiang.setShifouyouhui(true);
            } else {
                dingdanZixiang.setShifouyouhui(false);
            }

            return dingdanZixiang;
        }).collect(Collectors.toList());

        int insertList = ywYudingDingdanZiXiangMapper.insertList(list);
        if (insertList < 1) {
            throw new ArgumentException("预订失败");
        }
        //更新优惠
        /*list.stream().filter(e->e.getShifouyouhui()).map(e->{

        }).collect(Collectors.toList());*/
        List<DiscountsReservationQueryDTO> discountsReservationQueryList = params.getRoomReservationInfoDto().stream()
                .filter(e -> e.getRuzhuxingzhi() == YwYudingDingdanZixiangConstants.RUZHUXINGZHI_YINSI
                        && e.getMendianjia().compareTo(e.getYouhuijia()) != 0)
                .map(r -> {
                    DiscountsReservationQueryDTO queryDTO = new DiscountsReservationQueryDTO();
                    BeanUtils.copyProperties(r, queryDTO);
                    MhHuiyuanQinshu huiyuanQinshu = reservationCacheExtractor.getMhHuiyuanQinshu(r.getYudingrenId());
                    queryDTO.setZhengjianhao(huiyuanQinshu.getShenfenzhenghao());
                    queryDTO.setZhengjianleixing(MhHuiyuanQinshu.ZHENGJIANLEIXING_SHENFENZHENG);
                    queryDTO.setJieshushijian(r.getLikaishijian());
                    return queryDTO;
                }).collect(Collectors.toList());
        ResultVO discountResultVo = discountsService.reservation(discountsReservationQueryList);

        if (discountResultVo.getCode() == ResultVO.FAIL) {
            log.info("更新优惠失败，记录数据");
        }

        return ResultVO.success();
    }

    /**
     * 取消预订
     * <p>
     * 1.Redis加锁
     * 2.修改订单状态
     * 3.解锁订单下房间
     * 4.写入操作日志
     *
     * @param roomOrderCancelDTO
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    public ResultVO<String> cancel(RoomOrderCancelDTO roomOrderCancelDTO) {
        String traceId = CustomSecurity.getTraceID();
        log.info("traceId[" + traceId + "]" + JSONObject.toJSONString(roomOrderCancelDTO));

        ResultVO resultVO = ResultVO.fail();
        int jiudianId = 0;
        String redisLockKey = RedisConstants.HOTEL_ROOM_LOCK_KEY_PREFIX + jiudianId;
        try {
            //查找并判断订单是否可以取消
            int yudingId = roomOrderCancelDTO.getId();
            QueryConditions dingdanQueryCondition = new QueryConditions();
            dingdanQueryCondition.addCondition("huiyuanId", EConditionOperator.EQULS, userCache.getCurrentUserId());
            dingdanQueryCondition.addCondition("id", EConditionOperator.EQULS, yudingId);
            dingdanQueryCondition.addCondition("shanchubiaoshi", EConditionOperator.EQULS, SysDicConstant.DELFLAG_0);
            MyExample dingdanMyExample = new MyExample(YwYudingDingdan.class, dingdanQueryCondition);
            List<YwYudingDingdan> yudingDingdanList = ywYudingDingdanMapper.selectByExample(dingdanMyExample);
            if (CollectionUtils.isEmpty(yudingDingdanList)) {
                log.error("traceId[" + traceId + "]预订信息为空");
                TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
                resultVO.setMessage("预订信息为空");
                return resultVO;
            }

            YwYudingDingdan yudingDingdan = yudingDingdanList.get(0);
            jiudianId = yudingDingdan.getJiudianId();

            //使用redis，根据酒店id对房间操作加锁
            boolean lockRet = commonRedisTemplate.opsForValue().setIfAbsent(redisLockKey, jiudianId);
            if (!lockRet) {
                log.error("traceId[" + traceId + "]预订取消冲突，请重试");
                TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
                resultVO.setMessage("预订取消冲突，请重试");
                return resultVO;
            }

            byte zhuangtai = yudingDingdan.getZhuangtai();
            if (zhuangtai != YwYudingDingdanConstants.ZHUANGTAI_YITIJIAO) {
                log.error("traceId[" + traceId + "]该订单不能取消");
                TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
                resultVO.setMessage("该订单不能取消");
                return resultVO;
            }

            //修改订单状态
            yudingDingdan.setZhuangtai(YwYudingDingdanConstants.ZHUANGTAI_QUXIAO);
            int dingdanRet = ywYudingDingdanMapper.updateByPrimaryKeySelective(yudingDingdan);
            if (dingdanRet <= 0) {
                log.error("traceId[" + traceId + "]修改订单状态失败");
                TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
                resultVO.setMessage("修改订单状态失败");
                return resultVO;
            }

            //获取该订单下房间集合
            QueryConditions fangjianQueryCondition = new QueryConditions();
            fangjianQueryCondition.addCondition("dingdanId", EConditionOperator.EQULS, yudingId);
            fangjianQueryCondition.addCondition("shanchubiaoshi", EConditionOperator.EQULS, SysDicConstant.DELFLAG_0);
            MyExample fangjianMyExample = new MyExample(YwYudingDingdanZixiang.class, fangjianQueryCondition);
            List<YwYudingDingdanZixiang> fangjianResultList = ywYudingDingdanZiXiangMapper.selectByExample(fangjianMyExample);
            if (CollectionUtils.isEmpty(fangjianResultList)) {
                log.error("traceId[" + traceId + "]房间信息为空");
                TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
                resultVO.setMessage("房间信息为空");
                return resultVO;
            }

            //遍历房间，解锁
            for (YwYudingDingdanZixiang yudingDingdanZixiang : fangjianResultList) {
                QueryConditions fangtairiqijiluQueryCondition = new QueryConditions();
                fangtairiqijiluQueryCondition.addCondition("jiudianId", EConditionOperator.EQULS, yudingDingdanZixiang.getJiudianId());
                fangtairiqijiluQueryCondition.addCondition("fangjianId", EConditionOperator.EQULS, yudingDingdanZixiang.getFangjianId());
                fangtairiqijiluQueryCondition.addCondition("kaishishijian", EConditionOperator.EQULS, yudingDingdanZixiang.getRuzhushijian());
                fangtairiqijiluQueryCondition.addCondition("jieshushijian", EConditionOperator.EQULS, yudingDingdanZixiang.getLikaishijian());
                fangtairiqijiluQueryCondition.addCondition("shanchubiaoshi", EConditionOperator.EQULS, SysDicConstant.DELFLAG_0);
                fangtairiqijiluQueryCondition.addCondition("fangjianleibie", EConditionOperator.EQULS, YwFangtairiqijiluConstants.FANGJIANLEIBIE_FANGJIAN);
                MyExample fangtairiqijiluMyExample = new MyExample(YwFangtairiqijilu.class, fangtairiqijiluQueryCondition);
                YwFangtairiqijilu fangtairiqijilu = new YwFangtairiqijilu();
                fangtairiqijilu.setShanchubiaoshi(SysDicConstant.DELFLAG_1);

                int fangtaiRet = fangtairiqijiluMapper.updateByExampleSelective(fangtairiqijilu, fangtairiqijiluMyExample);
                if (fangtaiRet <= 0) {
                    log.error("traceId[" + traceId + "]修改房态失败");
                    TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
                    resultVO.setMessage("修改房态失败");
                    return resultVO;
                }
            }

            //取消订单时返回相应的年优惠次数
            List<DiscountsReservationQueryDTO> collect = fangjianResultList.stream().filter(e -> e.getShifouyouhui()).map(e -> {
                DiscountsReservationQueryDTO queryDTO = new DiscountsReservationQueryDTO();
                BeanUtils.copyProperties(e, queryDTO);
                queryDTO.setZhengjianhao(e.getYudingrenzhengjianhao());
                queryDTO.setZhengjianleixing(e.getYudingrenzhengjianleixing());
                queryDTO.setHuiyuanId(e.getYudingrenshenfenId());
                queryDTO.setJieshushijian(e.getLikaishijian());
                return queryDTO;
            }).collect(Collectors.toList());
            ResultVO resultVO1 = discountsService.cancelReservation(collect);
            if (resultVO1.getCode() != ResultVO.SUCCESS) {
                throw new ArgumentException("取消订单返回优惠次数失败");
            }

        } catch (Exception e) {
            log.error("traceId[" + traceId + "]预订取消失败，系统异常", e);
            throw new BizException("预订取消失败，系统异常");
        } finally {
            commonRedisTemplate.delete(redisLockKey);
        }

        resultVO.setCode(ResultVO.SUCCESS);
        resultVO.setMessage("操作成功");
        return resultVO;
    }

    public ResultVO<RoomOrderDetailQueryResultDTO> detail(RoomOrderDetailQueryDTO params) {
        ResultVO resultVO = ResultVO.fail();
        RoomOrderDetailQueryResultDTO resultDTO = new RoomOrderDetailQueryResultDTO();

        //获取订单主信息
        QueryConditions dingdanQueryConditions = new QueryConditions();
        dingdanQueryConditions.addCondition("id", EConditionOperator.EQULS, params.getId());
        dingdanQueryConditions.addCondition("huiyuanId", EConditionOperator.EQULS, userCache.getCurrentUserId());
        MyExample dingdanMyExample = new MyExample(YwYudingDingdan.class, dingdanQueryConditions);
        List<YwYudingDingdan> dingdanList = ywYudingDingdanMapper.selectByExample(dingdanMyExample);
        YwYudingDingdan mhDingdan = dingdanList.get(0);
        BeanUtils.copyProperties(mhDingdan, resultDTO);

        //获取订单会员名称
        resultDTO.setHuiyuanMingcheng(reservationCacheExtractor.getReservationUserNameById(resultDTO.getHuiyuanId()));

        //获取酒店详情
        ReservationHotelDetailQueryResultDTO hotelDetail = hotelService.getHotelInfoDtail(new HotelInfoDetailQueryDTO(mhDingdan.getJiudianId())).getData();
        resultDTO.setHotelDetail(hotelDetail);

        //获取订单房间信息
        List<YwYudingDingdanZixiang> mhDingdanZixiangs = ywYudingDingdanZiXiangMapper.selectByExample(Example.builder(YwYudingDingdanZixiang.class)
                .where(Sqls.custom()
                        .andEqualTo("dingdanId", params.getId())
                        .andEqualTo("shanchubiaoshi", YwYudingDingdanZixiangConstants.SHANCHUBIAOSHI_BUSHANCHU)).build());
        List<RoomOrderInfoQueryResultDto> roomOrderInfoQueryResultDtoList = mhDingdanZixiangs.stream().map(m -> {
            RoomOrderInfoQueryResultDto resultDto = new RoomOrderInfoQueryResultDto();
            BeanUtils.copyProperties(m, resultDto);
            return resultDto;
        }).collect(Collectors.toList());
        resultDTO.setInfoQueryResultDtoList(roomOrderInfoQueryResultDtoList);


        resultVO.setCode(ResultVO.SUCCESS);
        resultVO.setMessage("操作成功");
        resultVO.setData(resultDTO);
        return resultVO;
    }

    /**
     * 订单预订详情
     *
     * @param roomOrderBookingDetailQueryDTO
     * @return
     */
    public RoomOrderBookingDetailQueryResultDTO getBookingOrderDetail(RoomOrderBookingDetailQueryDTO roomOrderBookingDetailQueryDTO) {
        RoomOrderBookingDetailQueryResultDTO roomOrderBookingDetailQueryResultDTO = new RoomOrderBookingDetailQueryResultDTO();
        int yudingId = roomOrderBookingDetailQueryDTO.getYudingId();

        QueryConditions dingdanQueryConditions = new QueryConditions();
        dingdanQueryConditions.addCondition("id", EConditionOperator.EQULS, yudingId);
        dingdanQueryConditions.addCondition("huiyuanId", EConditionOperator.EQULS, userCache.getCurrentUserId());
        MyExample dingdanMyExample = new MyExample(YwYudingDingdan.class, dingdanQueryConditions);
        List<YwYudingDingdan> dingdanList = ywYudingDingdanMapper.selectByExample(dingdanMyExample);
        if (dingdanList == null || dingdanList.size() != 1) {
            return roomOrderBookingDetailQueryResultDTO;
        }

        YwYudingDingdan yudingDingdan = dingdanList.get(0);
        if (yudingDingdan == null) {
            return roomOrderBookingDetailQueryResultDTO;
        }

        BeanUtils.copyProperties(yudingDingdan, roomOrderBookingDetailQueryResultDTO);
        int ruzhutianshu = DateCalendarUtil.getNaturalDayDifferent(roomOrderBookingDetailQueryResultDTO.getRuzhushijian(), roomOrderBookingDetailQueryResultDTO.getLikaishijian());
        roomOrderBookingDetailQueryResultDTO.setRuzhutianshu(ruzhutianshu);

        QueryConditions fangjianQueryCondition = new QueryConditions();
        fangjianQueryCondition.addCondition("dingdanId", EConditionOperator.EQULS, yudingId);
        fangjianQueryCondition.addCondition("shanchubiaoshi", EConditionOperator.EQULS, SysDicConstant.DELFLAG_0);
        MyExample fangjianMyExample = new MyExample(YwYudingDingdanZixiang.class, fangjianQueryCondition);
        List<YwYudingDingdanZixiang> fangjianResultList = ywYudingDingdanZiXiangMapper.selectByExample(fangjianMyExample);

        List<YudingDingdanZixiangVO> dingdanZixiangVOList = fangjianResultList.stream().map(m -> {
            YudingDingdanZixiangVO dingdanZixiangVO = new YudingDingdanZixiangVO();
            BeanUtils.copyProperties(m, dingdanZixiangVO);

            YwFangjianleixing fangjianleixing = fangjianleixingMapper.selectByPrimaryKey(m.getFangxingId());

            if (m.getRuzhutianshu() != null){
                dingdanZixiangVO.setYouhuijia(m.getYouhuijia().multiply(BigDecimal.valueOf(m.getRuzhutianshu())));
            }

            dingdanZixiangVO.setSuoluetu(fangjianleixing.getSuoluetu());
            return dingdanZixiangVO;
        }).collect(Collectors.toList());

        roomOrderBookingDetailQueryResultDTO.setDingdanZixiangVOList(dingdanZixiangVOList);
        return roomOrderBookingDetailQueryResultDTO;
    }

    /**
     * 根据订单号修改订单评价状态
     *
     * @param params
     * @return
     */
    @Transactional
    public ResultVO submitComment(RoomOrderCommentSubmitQueryDto params) {
        ResultVO resultVO = ResultVO.fail();
        YwYudingDingdan mhDingdan = new YwYudingDingdan();
        mhDingdan.setPingjiazhuangtai(YwYudingDingdanConstants.PINGJIAZHUANGTAI_YIPINGJIA);

        int i = ywYudingDingdanMapper.updateByExampleSelective(mhDingdan, Example.builder(YwYudingDingdan.class)
                .where(Sqls.custom()
                        .andEqualTo("shanchubiaoshi", YwYudingDingdanZixiangConstants.SHANCHUBIAOSHI_BUSHANCHU)
                        .andEqualTo("dingdanhao", params.getDingdanhao())
                        .andEqualTo("huiyuanId", userCache.getCurrentUserId())

                ).build());
        if (i > 0) {
            return ResultVO.success();
        }

        return resultVO;
    }

    /**
     * 校验是否可以提交
     *
     * @param params
     */
    private void checkIsCanReservation(RoomOrderSubmitInfoDTO params) {

        //检验是否有余房
        //订单子项根据房型id和入住离开时间分组
        Map<String, List<RoomOrderInfoQueryDto>> roomTypeMap = params.getRoomReservationInfoDto().stream().collect(Collectors.groupingBy(r -> {
            String fangxingId = r.getFangxingId().toString();
            String startDate = r.getLikaishijian().toString();
            String endDate = r.getRuzhushijian().toString();
            return fangxingId + startDate + endDate;
        }));

        for (String key : roomTypeMap.keySet()) {
            List<RoomOrderInfoQueryDto> roomOrderInfoQueryDtos = roomTypeMap.get(key);
            RoomOrderInfoQueryDto sample = roomOrderInfoQueryDtos.get(0);
            RemainCountQueryDto remainCountQueryDto = new RemainCountQueryDto();
            remainCountQueryDto.setFangxingId(sample.getFangxingId());
            remainCountQueryDto.setEndTime(sample.getRuzhushijian());
            remainCountQueryDto.setStartTime(sample.getLikaishijian());
            ResultVO<Integer> resultVO = dailyManageApi.queryRemainRoomCount(remainCountQueryDto);
            if (resultVO.getCode() != ResultVO.SUCCESS) {
                throw new ArgumentException("调用查询剩余房间数失败");
            }
            Integer count = resultVO.getData();
            if (count < roomOrderInfoQueryDtos.size()) {
                throw new ArgumentException(sample.getFangxingmingcheng() + "房间数不足");
            }
        }


        //最多预订四个房间
        if (params.getRoomReservationInfoDto().size() > 4) {
            throw new ArgumentException("最多预订四个房间");
        }
        //获取联系人信息
        params.getRoomReservationInfoDto().forEach(r -> {
            MhHuiyuanQinshu mhHuiyuanQinshu = reservationCacheExtractor.getMhHuiyuanQinshu(r.getYudingrenId());
            if (mhHuiyuanQinshu == null) {
                throw new ArgumentException("获取联系人信息失败");
            }
            r.setYudingxingming(mhHuiyuanQinshu.getXingming());
            r.setYudingrenzhengjianhao(mhHuiyuanQinshu.getShenfenzhenghao());
            r.setGuanxi(mhHuiyuanQinshu.getGuanxi());
        });

        //校验入住人不能多次出现
        Map<Integer, List<RoomOrderInfoQueryDto>> map = params.getRoomReservationInfoDto().stream()
                .collect(Collectors.groupingBy(RoomOrderInfoQueryDto::getYudingrenId));
        for (Integer key : map.keySet()) {
            if (map.get(key).size() > 1) {
                throw new ArgumentException("入住人" + map.get(key).get(0).getYudingxingming() + "不能重复出现");
            }
        }

        // 得到房型价格
        params.getRoomReservationInfoDto().forEach(r -> {
            r.setMendianjia(hotelInfoCacheExtractor.getRoomTypePriceById(r.getFangxingId()));
        });


        //计算每个房间优惠后总价
        BigDecimal total = params.getRoomReservationInfoDto().stream()
                .map(e->{
                    //拿到该房间的优惠过后的总价(不管是否优惠)
                    BigDecimal discountPrice = getDiscountPrice(e);
                    e.setYouhuijia(discountPrice.divide(new BigDecimal(DateCalendarUtil.getDiffDays(e.getRuzhushijian(), e.getLikaishijian()))));
                    return discountPrice;
                })
                .reduce(BigDecimal::add)
                .orElse(new BigDecimal(0));
        //计算订单总计优惠了多少钱
        BigDecimal youhuijineTotal = params.getRoomReservationInfoDto().stream()
                .map(e -> {
                    log.info("门店价乘以天数：{}，优惠价：{}",e.getMendianjia().multiply(new BigDecimal(DateCalendarUtil.getDiffDays(e.getRuzhushijian(), e.getLikaishijian()))).doubleValue(),e.getYouhuijia().doubleValue());
                    log.info("减去的结果：{}",e.getMendianjia().multiply(new BigDecimal(DateCalendarUtil.getDiffDays(e.getRuzhushijian(), e.getLikaishijian()))).subtract(e.getYouhuijia()));
                    return e.getMendianjia().subtract(e.getYouhuijia()).multiply(new BigDecimal(DateCalendarUtil.getDiffDays(e.getRuzhushijian(), e.getLikaishijian())));
                })
                .reduce(BigDecimal::add)
                .orElse(new BigDecimal(0));

        //订单总价
        params.setDingdanzongjia(total);
        params.setYouhuijine(youhuijineTotal);
        //params.setYouhuijine();
    }


    /**
     * 得到优惠价*天数*房间数
     *
     * @param queryDto
     * @return
     */
    private BigDecimal getDiscountPrice(RoomOrderInfoQueryDto queryDto) {
        DiscountsIfCanQueryDTO queryDTO = new DiscountsIfCanQueryDTO();
        queryDTO.setJieshushijian(queryDto.getLikaishijian());
        queryDTO.setRuzhushijian(queryDto.getRuzhushijian());
        queryDTO.setContactIds(queryDto.getYudingrenId());
        queryDTO.setRuzhuxingzhi(queryDto.getRuzhuxingzhi());
        queryDTO.setFangxingId(queryDto.getFangxingId());
        queryDTO.setShuliang(queryDto.getShuliang());
        ResultVO<DiscountsIfCanQueryResultDTO> discountsIfCanQueryResultDTOResultVO = discountsService.queryDiscountsPrice(queryDTO);


        if (discountsIfCanQueryResultDTOResultVO.getCode() == ResultVO.FAIL) {
            throw new ArgumentException("得到优惠价失败");
        }
        return discountsIfCanQueryResultDTOResultVO.getData().getDiscountsPrice();
    }


    /**
     * 是否可以优惠
     * true:可以享受优惠
     * flase：不能享受优惠
     *
     * @param queryDto
     * @return
     */
    private Boolean ifCanDiscount(RoomOrderInfoQueryDto queryDto) {
        DiscountsIfCanQueryDTO queryDTO = new DiscountsIfCanQueryDTO();
        queryDTO.setJieshushijian(queryDto.getLikaishijian());
        queryDTO.setContactIds(queryDto.getYudingrenId());
        queryDTO.setRuzhushijian(queryDto.getRuzhushijian());
        queryDTO.setRuzhuxingzhi(queryDto.getRuzhuxingzhi());
        queryDTO.setFangxingId(queryDto.getFangxingId());
        queryDTO.setShuliang(queryDto.getShuliang());
        ResultVO<BigDecimal> discounts = discountsService.getDiscountAmount(queryDTO);

        if (discounts.getCode() == ResultVO.FAIL) {
            throw new ArgumentException("得到优惠天数失败");
        }
        //如果可享受的优惠次数为0，则不能优惠，反之则可以优惠
        return discounts.getData().compareTo(new BigDecimal(0)) != 0;
    }

}
